"use strict";
const range_width = 16384;
const range_height = 16384;

const unit_range_width = 200;
const unit_range_height = 200;
class FoodEffect {
	constructor(config /* ? : FoodEffectConfig*/ ) {
		this.add_body = 0
		this.add_speed = 0
		this.add_sensitivity = 0
		config && this.importConfig(config);
	}
	importConfig(config /*: FoodEffectConfig*/ ) {
		config.add_body && (this.add_body = config.add_body)
		config.add_speed && (this.add_speed = config.add_speed)
		config.add_sensitivity && (this.add_sensitivity = config.add_sensitivity)
	}
}

class Food {
	constructor(x, y, effect_config) {
		this.x = x;
		this.y = y;
		//相对FootSet中的坐标
		this.rel_x = x;
		this.rel_y = y;
		this.effect = new FoodEffect(effect_config);
	}
	update() {}
	toJSON() {
		return {
			x: this.x,
			y: this.y,
			effect: this.effect
		}
	}
	effectFood(snake) {
		var food_effect = this.effect
		if (food_effect.add_body) {
			snake.addBody(food_effect.add_body)
		}
		if (food_effect.add_speed) {
			snake.addSpeed(food_effect.add_speed)
		}
		if (food_effect.add_sensitivity) {
			snake.addSensitivity(food_effect.add_sensitivity)
		}
	}
}

const FOOD_SET_UNIT_SIZE = 600;

class FoodSet extends Array {
	// set_level: number
	// /**PIXI.Container的width/height/x/y都是计算属性，这里进行静态缓存 */
	// set_width: number
	// set_height: number
	// set_half_width: number
	// set_half_height: number
	// set_x: number
	// set_y: number
	// childConSet: PIXI.Container[];
	/**
	 * @parame index: 在2*2的矩阵空间中的位置[0~3]
	 */
	constructor(level /*: number*/ , index /* ? : number*/ , item_set_list /*? : FoodSet[]*/ ) {
		super()
		this.set_level = level;
		const size = FOOD_SET_UNIT_SIZE;
		if (level) {
			//一开始是一个2*2的矩阵
			for (var y = 0; y < 2; y += 1) {
				for (var x = 0; x < 2; x += 1) {
					var item_index = x + y * 2;
					//递归生成
					var item_set = item_set_list && item_set_list[item_index] || new FoodSet(level - 1, item_index);
					this.push(item_set)
				}
			}
			this.update = this._update_sets;
		} else {
			// 单位空间的大小40*40
			this.width = FOOD_SET_UNIT_SIZE;
			this.height = FOOD_SET_UNIT_SIZE;
			this.update = this._update_foods;
		}
		this.set_height = this.set_width = Math.pow(2, level) * size;
		this.set_half_width = this.set_width / 2
		this.set_half_height = this.set_height / 2
		if (index === 1) {
			this.x = this.set_width
		} else if (index === 2) {
			this.y = this.set_height
		} else if (index === 3) {
			this.x = this.set_width
			this.y = this.set_height
		}
		this.set_x = this.x
		this.set_y = this.y
	};
	// private _lock: boolean = false
	// private _lock_ti: any
	get lock() {
		return this._lock
	}
	set lock(_lock /*: boolean*/ ) {
		_lock = !!_lock;
		if (_lock === this._lock) {
			return
		}
		this._lock = _lock;
		if (this.set_level) {
			this[0].lock = _lock;
			this[1].lock = _lock;
			this[2].lock = _lock;
			this[3].lock = _lock;
		}
	}
	addFood(food /*: Food*/ , x /*: number*/ , y /*: number*/ ) {
		x === undefined && (x = food.x);
		y === undefined && (y = food.y);
		if (this.set_level) { //不为0，转交给下一级
			var index = 0;
			if (x > this.set_half_width) {
				x -= this.set_half_width;
				index += 1
			}
			if (y > this.set_half_height) {
				y -= this.set_half_height;
				index += 2
			}
			var food_set = /*< FoodSet > */ this[index];
			food_set.lock = false;
			food_set.addFood(food, x, y);
		} else {
			this.lock = false;
			this.push(food)
			food.rel_x = x;
			food.rel_y = y;
		}
	};
	/**获取发生碰撞的元素 */
	getCollisionItemWithCircle(x /*: number*/ , y /*: number*/ , r /*: number = 0*/ , filter /*? : (item: PIXI.DisplayObject, x: number, y: number, index: number) => boolean*/ ) /*: PIXI.DisplayObject[] */ {
		if (this.set_level) { //不为0，转交给下一级
			var res = [];
			var index = 0;
			var set_half_width = this.set_half_width;
			var set_half_height = this.set_half_height;
			if (x < 0 || y < 0) {
				this.lock = true;
				return res
			}
			if (x > set_half_width) {
				index += 1
			}
			if (y > set_half_height) {
				index += 2
			}
			//半径的存在可能会触及其它空间领域
			var check_indexs = {
				[index]: 1
			};
			if (index % 2) { //1,3如果在右半块区域，检测是否触及左半快区域
				if (x - r <= set_half_width) {
					check_indexs[index - 1] = 1
				}
			} else { //0,2如果在左半块区域，检测是否触及右半块区域
				if (x + r > set_half_width) {
					check_indexs[index + 1] = 1
				}
			}
			if (index > 1) { //2,3如果在下半块区域，检测是否触及上半快区域
				if (y - r <= set_half_height) {
					check_indexs[index - 2] = 1
				}
			} else { //0,1如果在上半块区域，检测是否触及下半快区域
				if (y + r > set_half_height) {
					check_indexs[index + 2] = 1
				}
			}
			[0, 1, 2, 3].forEach(index => {
				var food_set = /*< FoodSet >*/ this[index]
				if (check_indexs[index]) {
					var _x = x;
					var _y = y;
					if (index % 2) {
						_x -= set_half_width;
					}
					if (index > 1) {
						_y -= set_half_height;
					}
					food_set.lock = false;
					res.push.apply(res, food_set.getCollisionItemWithCircle(_x, _y, r, filter))
				} else {
					food_set.lock = true;
				}
			})

			return res;
		} else {
			filter || (filter = item => {
				var item_bounds = item.getBounds()
					//TODO:圆与长方形的检测，
				if (item_bounds) {

				}
				return true;
			})
			return this.children.filter((item, index) => {
				return filter(item, x, y, index)
			});
		}
	};
	update(time /* ? : number*/ ) {};
	/*private*/
	_update_foods(time /* ? : number*/ ) {
		for (var i = 0, arr = this.children, food /*: Food*/ ; food = /* < Food > */ arr[i]; i += 1) {
			food instanceof Food && food.update(time);
		}
	};
	/*private*/
	_update_sets(time /* ? : number*/ ) {
		this[0].update(time);
		this[1].update(time);
		this[2].update(time);
		this[3].update(time);
	};
	/**获取一个范围内的食物*/
	getRangeFoods(x, y, width, height) /*:Food[]*/ {
		if (this.set_level) { //不为0，转交给下一级
			var res = [];
			var index = 0;
			var set_half_width = this.set_half_width;
			var set_half_height = this.set_half_height;

			if (x > set_half_width) {
				index += 1
			}
			if (y > set_half_height) {
				index += 2
			}
			//矩形是否覆盖其它区域
			var check_indexs = {
				[index]: 1
			};
			if (!(index % 2)) { //0,2如果在左半块区域，检测是否触及右半块区域
				if (x + width > set_half_width) {
					check_indexs[index + 1] = 1
				}
			}
			if (!(index > 1)) { //0,1如果在上半块区域，检测是否触及下半快区域
				if (y + height > set_half_height) {
					check_indexs[index + 2] = 1
					if (check_indexs[1]) {
						check_indexs[3] = 1;
					}
				}
			}
			[0, 1, 2, 3].forEach(index => {
				var food_set = /*< FoodSet >*/ this[index]
				if (check_indexs[index]) {
					var _x = x;
					var _y = y;
					if (index % 2) {
						_x -= set_half_width;
					}
					if (index > 1) {
						_y -= set_half_height;
					}
					food_set.lock = false;
					res.push.apply(res, food_set.getRangeFoods(_x, _y, width, height))
				} else {
					food_set.lock = true;
				}
			})

			return res;
		} else {
			// console.log(`check :${x}~${x+width} :${y}~${y+height}`, this.length)
			const r_x = x + width;
			const b_y = y + height;
			return this.filter((item, index) => {
				return item.rel_x >= x && item.rel_x <= r_x && item.rel_y >= y && item.rel_y <= b_y
			});
		}
	};
	/**移除某个点上的食物*/
	removeFood(x, y) /*boolean*/ {
		if (this.set_level) { //不为0，转交给下一级
			var index = 0;
			var set_half_width = this.set_half_width;
			var set_half_height = this.set_half_height;
			if (x > set_half_width) {
				index += 1
			}
			if (y > set_half_height) {
				index += 2
			}
			var food_set = /*< FoodSet >*/ this[index]

			var _x = x;
			var _y = y;
			if (index % 2) {
				_x -= set_half_width;
			}
			if (index > 1) {
				_y -= set_half_height;
			}
			food_set.lock = false;
			return food_set.removeFood(_x, _y)

		} else {
			var res;
			this.some((item, i) => {
				if (item.rel_x === x && item.rel_y === y) {
					res = this.splice(i, 1)[0];
					return true;
				}
			});
			return res;
		}
	}
}

/*export*/
class FoodSetManager extends Array {
	// food_set = new FoodSet(1)
	// set_level: number = 1
	// set_width: number
	// set_height: number
	// set_half_width: number
	// set_half_height: number
	// set_x: number
	// set_y: number
	constructor() {
		super();
		this.food_set = new FoodSet(1);
		this.set_level = 1
			// super()
		this.push(this.food_set);
		this._cache_info();
	};
	/*private*/
	_cache_info() {
		const food_set = this.food_set;
		this.set_width = food_set.set_width
		this.set_height = food_set.set_height
		this.set_half_width = food_set.set_half_width
		this.set_half_height = food_set.set_half_height
		this.set_x = this.x
		this.set_y = this.y
	};
	upLevel(up_level /*: number = 1*/ ) {
		up_level || (up_level = 1);
		while (up_level > 0) {
			var set_level = this.set_level += 1;
			this.removeChild(this.food_set);
			this.food_set = new FoodSet(set_level, 0, [this.food_set]);
			this.push(this.food_set);
			up_level -= 1
		}

		this._cache_info();
	};
	addFood(food /*: Food*/ , x /*: number*/ , y /*: number*/ ) {
		if (x > this.set_width || y > this.set_height) {
			this.upLevel();
			return this.addFood(food, x, y);
		}
		return this.food_set.addFood(food, x, y)
	};
	getCollisionItemWithCircle(x /*: number*/ , y /*: number*/ , r /*: number = 0*/ , filter /*? : (item: PIXI.DisplayObject, x: number, y: number, index: number) => boolean*/ ) {
		return this.food_set.getCollisionItemWithCircle(x, y, r, filter);
	};
	update(time /*? : number*/ ) {
		return this.food_set.update(time)
	};
	/**获取一个范围内的食物*/
	getRangeFoods(x, y, width, height) /*:Food[]*/ {
		return this.food_set.getRangeFoods(x, y, width, height);
	};
	/**移除某个点上的食物*/
	removeFood(x, y) {
		return this.food_set.removeFood(x, y);
	}
};


exports.FoodEffect = FoodEffect;
exports.Food = Food;
exports.FoodSet = FoodSet;
exports.FoodSetManager = FoodSetManager;
exports.range_width = range_width;
exports.range_height = range_height;
exports.unit_range_width = unit_range_width;
exports.unit_range_height = unit_range_height;

exports.food_set_manager = new FoodSetManager();